package com.itheima.stock.service.impl;

import com.google.common.collect.Lists;
import com.itheima.stock.constant.ParseType;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.domain.InnerMarketDomain;
import com.itheima.stock.pojo.entity.StockMarketIndexInfo;
import com.itheima.stock.pojo.entity.StockRtInfo;
import com.itheima.stock.pojo.vo.StockInfoConfig;
import com.itheima.stock.service.StockTimerTaskService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.utils.DomainTransferUtil;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
    // 请求路径  大盘标识
    @Autowired
    private StockInfoConfig stockInfoConfig;
    // 远程访问的RestTemplate
    @Autowired
    private RestTemplate restTemplate;
    // 生成唯一标记
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    // 股票数据解析工具类
    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;

    // 个股业务对象: 获取个股的code码
    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 注入线程池对象
     */
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 拉取个股数据信息
     */
    @Override
    public void getStockRtIndex() {
        //批量获取股票ID集合
        List<String> stockIds = stockBusinessMapper.getStockIds();
        //计算出符合sina命名规范的股票id数据
        stockIds = stockIds.stream().map(id -> {
            return id.startsWith("6") ? "sh" + id : "sz" + id;
        }).collect(Collectors.toList());
        //设置公共请求头对象
        //设置请求头数据
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","https://finance.sina.com.cn/stock/");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        HttpEntity<String> entity = new HttpEntity<>(headers);
        //一次性查询过多，我们将需要查询的数据先进行分片处理，每次最多查询20条股票数据
        Lists.partition(stockIds,5).forEach(list->{
            // 从线程池中获取线程,执行任务
            threadPoolTaskExecutor.execute(()->{
                String name = Thread.currentThread().getName();
                System.out.println("----------------------"+name);
                //拼接股票url地址
                String stockUrl=stockInfoConfig.getMarketUrl()+String.join(",",list);
                System.out.println("请求路径: "+stockUrl);
                //获取响应数据
                String result = restTemplate.postForObject(stockUrl,entity,String.class);
                List<StockRtInfo> infos = parserStockInfoUtil.parser4StockOrMarketInfo(result, ParseType.ASHARE);
                log.info("数据量：{}",infos.size());
                System.out.println(infos);
                //TODO 批量插入
                int i = stockRtInfoMapper.insertBatch(infos);
                if (i>0){
                    System.out.println("添加成功...");
                }
            });

        });
    }

    /**
     * 拉取大盘数据信息
     */
    @Override
    public void getInnerMarketInfo() {
        //1.定义访问的url   http://hq.sinajs.cn/list=sh000001,sz399001
        String url = stockInfoConfig.getMarketUrl() + String.join(",",stockInfoConfig.getInner());
        System.out.println("大盘数据拉取路径: "+url);
        //2.调用restTemplate采集数据
        //2.1 组装请求头
        HttpHeaders headers = new HttpHeaders();
        //必须填写，否则数据采集不到
        headers.add("Referer","https://finance.sina.com.cn/stock/");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //2.2 组装请求对象
        HttpEntity<Object> entity = new HttpEntity<>(headers);
        //2.3 resetTemplate发起请求
        String resString = restTemplate.postForObject(url, entity, String.class);
        System.out.println("拉取到的数据为: "+resString);
        //var hq_str_sh000001="上证指数,3172.3759,3169.5072,3177.5465,3179.2396,3166.2674,0,0,81475126,107756881851,
        // 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2023-01-11,10:15:41,00,";
        //var hq_str_sz399001="深证成指,11498.970,11506.794,11512.931,11518.517,11469.250,0.000,0.000,13186311080,
        // 155861627920.009,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,2023-01-11,10:15:39,00";
//        String reg="var hq_str_(.+)=\"(.+)\";";
//        //编译表达式,获取编译对象
//        Pattern pattern = Pattern.compile(reg);
//        //匹配字符串
//        Matcher matcher = pattern.matcher(resString);
//        // 定义list集合用于收集解析到的数据信息
//        ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
//        //判断是否有匹配的数值
//        while (matcher.find()){
//            //获取大盘的code
//            String marketCode = matcher.group(1);
//            //获取其它信息，字符串以逗号间隔
//            String otherInfo=matcher.group(2);
//            //以逗号切割字符串，形成数组
//            String[] splitArr = otherInfo.split(",");
//            //大盘名称
//            String marketName=splitArr[0];
//            //获取当前大盘的开盘点数
//            BigDecimal openPoint=new BigDecimal(splitArr[1]);
//            //前收盘点
//            BigDecimal preClosePoint=new BigDecimal(splitArr[2]);
//            //获取大盘的当前点数
//            BigDecimal curPoint=new BigDecimal(splitArr[3]);
//            //获取大盘最高点
//            BigDecimal maxPoint=new BigDecimal(splitArr[4]);
//            //获取大盘的最低点
//            BigDecimal minPoint=new BigDecimal(splitArr[5]);
//            //获取成交量
//            Long tradeAmt=Long.valueOf(splitArr[8]);
//            //获取成交金额
//            BigDecimal tradeVol=new BigDecimal(splitArr[9]);
//            //时间
//            Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();
//            //组装entity对象
//            StockMarketIndexInfo info = StockMarketIndexInfo.builder()
//                    .id(idWorker.nextId())
//                    .marketCode(marketCode)
//                    .marketName(marketName)
//                    .curPoint(curPoint)
//                    .openPoint(openPoint)
//                    .preClosePoint(preClosePoint)
//                    .maxPoint(maxPoint)
//                    .minPoint(minPoint)
//                    .tradeVolume(tradeVol)
//                    .tradeAmount(tradeAmt)
//                    .curTime(curTime)
//                    .build();
//            //收集封装的对象，方便批量插入
//            list.add(info);
//        }
        List<StockMarketIndexInfo> list = parserStockInfoUtil.parser4StockOrMarketInfo(resString, ParseType.INNER);
        log.info("采集的当前大盘数据：{}",list);
        //批量插入
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        // todo:落库,批量添加
        int i = stockMarketIndexInfoMapper.insertBatch(list);
        if (i>0){
            System.out.println("添加成功");
        }
        // todo: StockMarketIndexInfo中的数据与数据库表字段对应
        //  InnerMarketDomain中的数据信息与前端需要的结果对应,往MQ中存放数据时,存放的是与前端对应的数据
        //数据转化成domain对象
        List<InnerMarketDomain> datas = list.stream().map(enity -> {
            return DomainTransferUtil.transferMarketInfo(enity);
        }).collect(Collectors.toList());
        // 往MQ中存放数据
        rabbitTemplate.convertAndSend("stockExchange","inner.market",datas);
    }
}
